home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / manageme / tcpdump-.001 / tcpdump-~ / tcpdump-3.0.2-linux / tcpdump-3.0.2 / print-bootp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-15  |  8.9 KB  |  358 lines

  1. /*
  2.  * Copyright (c) 1990, 1991, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  *
  21.  * Format and print bootp packets.
  22.  */
  23. #ifndef lint
  24. static char rcsid[] =
  25.     "@(#) $Header: print-bootp.c,v 1.30 94/06/14 20:17:37 leres Exp $ (LBL)";
  26. #endif
  27.  
  28. #include <sys/param.h>
  29. #include <sys/time.h>
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32.  
  33. #include <net/if.h>
  34.  
  35. #include <netinet/in.h>
  36. #include <netinet/if_ether.h>
  37.  
  38. #include <ctype.h>
  39. #include <stdio.h>
  40.  
  41. #include "interface.h"
  42. #include "addrtoname.h"
  43. #include "bootp.h"
  44.  
  45. static void rfc1048_print(const u_char *, int);
  46. static void cmu_print(const u_char *, int);
  47.  
  48. static char tstr[] = " [|bootp]";
  49.  
  50. /*
  51.  * Print bootp requests
  52.  */
  53. void
  54. bootp_print(register const u_char *cp, int length,
  55.         u_short sport, u_short dport)
  56. {
  57.     register const struct bootp *bp;
  58.     static u_char vm_cmu[4] = VM_CMU;
  59.     static u_char vm_rfc1048[4] = VM_RFC1048;
  60.     const u_char *ep;
  61.  
  62. #define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
  63.  
  64.     bp = (struct bootp *)cp;
  65.     /* 'ep' points to the end of avaible data. */
  66.     ep = snapend;
  67.  
  68.     TCHECK(bp->bp_op, sizeof(bp->bp_op));
  69.     switch (bp->bp_op) {
  70.  
  71.     case BOOTREQUEST:
  72.         /* Usually, a request goes from a client to a server */
  73.         if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS)
  74.             printf(" (request)");
  75.         break;
  76.  
  77.     case BOOTREPLY:
  78.         /* Usually, a reply goes from a server to a client */
  79.         if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC)
  80.             printf(" (reply)");
  81.         break;
  82.  
  83.     default:
  84.         printf(" bootp-#%d", bp->bp_op);
  85.     }
  86.  
  87.     TCHECK(bp->bp_secs, sizeof(bp->bp_secs));
  88.  
  89.     /* The usual hardware address type is 1 (10Mb Ethernet) */
  90.     if (bp->bp_htype != 1)
  91.         printf(" htype-#%d", bp->bp_htype);
  92.  
  93.     /* The usual length for 10Mb Ethernet address is 6 bytes */
  94.     if (bp->bp_htype != 1 || bp->bp_hlen != 6)
  95.         printf(" hlen:%d", bp->bp_hlen);
  96.  
  97.     /* Only print interesting fields */
  98.     if (bp->bp_hops)
  99.         printf(" hops:%d", bp->bp_hops);
  100.     if (bp->bp_xid)
  101.         printf(" xid:0x%x", ntohl(bp->bp_xid));
  102.     if (bp->bp_secs)
  103.         printf(" secs:%d", ntohs(bp->bp_secs));
  104.  
  105.     /* Client's ip address */
  106.     TCHECK(bp->bp_ciaddr, sizeof(bp->bp_ciaddr));
  107.     if (bp->bp_ciaddr.s_addr)
  108.         printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));
  109.  
  110.     /* 'your' ip address (bootp client) */
  111.     TCHECK(bp->bp_yiaddr, sizeof(bp->bp_yiaddr));
  112.     if (bp->bp_yiaddr.s_addr)
  113.         printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));
  114.  
  115.     /* Server's ip address */
  116.     TCHECK(bp->bp_siaddr, sizeof(bp->bp_siaddr));
  117.     if (bp->bp_siaddr.s_addr)
  118.         printf(" S:%s", ipaddr_string(&bp->bp_siaddr));
  119.  
  120.     /* Gateway's ip address */
  121.     TCHECK(bp->bp_giaddr, sizeof(bp->bp_giaddr));
  122.     if (bp->bp_giaddr.s_addr)
  123.         printf(" G:%s", ipaddr_string(&bp->bp_giaddr));
  124.  
  125.     /* Client's Ethernet address */
  126.     if (bp->bp_htype == 1 && bp->bp_hlen == 6) {
  127.         register const struct ether_header *eh;
  128.         register const char *e;
  129.  
  130.         TCHECK(bp->bp_chaddr[0], 6);
  131.         eh = (struct ether_header *)packetp;
  132.         if (bp->bp_op == BOOTREQUEST)
  133.             e = (const char *)ESRC(eh);
  134.         else if (bp->bp_op == BOOTREPLY)
  135.             e = (const char *)EDST(eh);
  136.         else
  137.             e = 0;
  138.         if (e == 0 || bcmp((char *)bp->bp_chaddr, e, 6) != 0)
  139.             printf(" ether %s", etheraddr_string(bp->bp_chaddr));
  140.     }
  141.  
  142.     TCHECK(bp->bp_sname[0], 1);        /* check first char only */
  143.     if (*bp->bp_sname) {
  144.         printf(" sname ");
  145.         if (fn_print(bp->bp_sname, ep)) {
  146.             fputs(tstr + 1, stdout);
  147.             return;
  148.         }
  149.     }
  150.     TCHECK(bp->bp_sname[0], 1);        /* check first char only */
  151.     if (*bp->bp_file) {
  152.         printf(" file ");
  153.         if (fn_print(bp->bp_file, ep)) {
  154.             fputs(tstr + 1, stdout);
  155.             return;
  156.         }
  157.     }
  158.  
  159.     /* Decode the vendor buffer */
  160.     TCHECK(bp->bp_vend[0], sizeof(bp->bp_vend));
  161.     length -= sizeof(*bp) - sizeof(bp->bp_vend);
  162.     if (bcmp((char *)bp->bp_vend, (char *)vm_rfc1048,
  163.          sizeof(u_int32)) == 0)
  164.         rfc1048_print(bp->bp_vend, length);
  165.     else if (bcmp((char *)bp->bp_vend, (char *)vm_cmu,
  166.               sizeof(u_int32)) == 0)
  167.         cmu_print(bp->bp_vend, length);
  168.     else {
  169.         u_int32 ul;
  170.  
  171.         bcopy((char *)bp->bp_vend, (char *)&ul, sizeof(ul));
  172.         if (ul != 0)
  173.             printf("vend-#0x%x", ul);
  174.     }
  175.  
  176.     return;
  177. trunc:
  178.     fputs(tstr, stdout);
  179. #undef TCHECK
  180. }
  181.  
  182. /* The first character specifies the format to print */
  183. static struct token tag2str[] = {
  184. /* RFC1048 tags */
  185.     { TAG_PAD,        " PAD" },
  186.     { TAG_SUBNET_MASK,    "iSM" },    /* subnet mask (RFC950) */
  187.     { TAG_TIME_OFFSET,    "lTZ" },    /* seconds from UTC */
  188.     { TAG_GATEWAY,        "iDG" },    /* default gateway */
  189.     { TAG_TIME_SERVER,    "iTS" },    /* time servers (RFC868) */
  190.     { TAG_NAME_SERVER,    "iIEN" },    /* IEN name servers (IEN116) */
  191.     { TAG_DOMAIN_SERVER,    "iNS" },    /* domain name (RFC1035) */
  192.     { TAG_LOG_SERVER,    "iLOG" },    /* MIT log servers */
  193.     { TAG_COOKIE_SERVER,    "iCS" },    /* cookie servers (RFC865) */
  194.     { TAG_LPR_SERVER,    "iLPR" },    /* lpr server (RFC1179) */
  195.     { TAG_IMPRESS_SERVER,    "iIM" },    /* impress servers (Imagen) */
  196.     { TAG_RLP_SERVER,    "iRL" },    /* resource location (RFC887) */
  197.     { TAG_HOSTNAME,        "aHN" },    /* ascii hostname */
  198.     { TAG_BOOTSIZE,        "sBS" },    /* 512 byte blocks */
  199.     { TAG_END,        " END" },
  200. /* RFC1497 tags */
  201.     { TAG_DUMPPATH,        "aDP" },
  202.     { TAG_DOMAINNAME,    "aDN" },
  203.     { TAG_SWAP_SERVER,    "iSS" },
  204.     { TAG_ROOTPATH,        "aRP" },
  205.     { TAG_EXTPATH,        "aEP" },
  206.     { 0,            NULL }
  207. };
  208.  
  209. static void
  210. rfc1048_print(register const u_char *bp, register int length)
  211. {
  212.     register u_char tag;
  213.     register const u_char *ep;
  214.     register u_int len, size;
  215.     register const char *cp;
  216.     register char c;
  217.     int first;
  218.     u_int32 ul;
  219.     u_short us;
  220.  
  221.     printf(" vend-rfc1048");
  222.  
  223.     /* Setup end pointer */
  224.     ep = bp + length;
  225.  
  226.     /* Step over magic cookie */
  227.     bp += sizeof(int32);
  228.  
  229.     /* Loop while we there is a tag left in the buffer */
  230.     while (bp + 1 < ep) {
  231.         tag = *bp++;
  232.         if (tag == TAG_PAD)
  233.             continue;
  234.         if (tag == TAG_END)
  235.             return;
  236.         cp = tok2str(tag2str, "?T%d", tag);
  237.         c = *cp++;
  238.         printf(" %s:", cp);
  239.  
  240.         /* Get the length; check for truncation */
  241.         if (bp + 1 >= ep) {
  242.             fputs(tstr, stdout);
  243.             return;
  244.         }
  245.         len = *bp++;
  246.         if (bp + len >= ep) {
  247.             fputs(tstr, stdout);
  248.             return;
  249.         }
  250.  
  251.         /* Print data */
  252.         size = len;
  253.         if (c == '?') {
  254.             /* Base default formats for unknown tags on data size */
  255.             if (size & 1)
  256.                 c = 'b';
  257.             else if (size & 2)
  258.                 c = 's';
  259.             else
  260.                 c = 'l';
  261.         }
  262.         first = 1;
  263.         switch (c) {
  264.  
  265.         case 'a':
  266.             /* ascii strings */
  267.             (void)fn_printn(bp, size, NULL);
  268.             bp += size;
  269.             size = 0;
  270.             break;
  271.  
  272.         case 'i':
  273.         case 'l':
  274.             /* ip addresses/32-bit words */
  275.             while (size >= sizeof(ul)) {
  276.                 if (!first)
  277.                     putchar(',');
  278.                 bcopy((char *)bp, (char *)&ul, sizeof(ul));
  279.                 if (c == 'i')
  280.                     printf("%s", ipaddr_string(&ul));
  281.                 else
  282.                     printf("%lu", ul);
  283.                 bp += sizeof(ul);
  284.                 size -= sizeof(ul);
  285.                 first = 0;
  286.             }
  287.             break;
  288.  
  289.         case 's':
  290.             /* shorts */
  291.             while (size >= sizeof(us)) {
  292.                 if (!first)
  293.                     putchar(',');
  294.                 bcopy((char *)bp, (char *)&us, sizeof(us));
  295.                 printf("%d", us);
  296.                 bp += sizeof(us);
  297.                 size -= sizeof(us);
  298.                 first = 0;
  299.             }
  300.             break;
  301.  
  302.         case 'b':
  303.         default:
  304.             /* Bytes */
  305.             while (size > 0) {
  306.                 if (!first)
  307.                     putchar('.');
  308.                 printf("%d", *bp);
  309.                 ++bp;
  310.                 --size;
  311.                 first = 0;
  312.             }
  313.             break;
  314.         }
  315.         /* Data left over? */
  316.         if (size)
  317.             printf("[len %d]", len);
  318.     }
  319. }
  320.  
  321. static void
  322. cmu_print(register const u_char *bp, register int length)
  323. {
  324.     register const struct cmu_vend *cmu;
  325.     register const u_char *ep;
  326.     char *fmt = " %s:%s";
  327.  
  328. #define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
  329. #define PRINTCMUADDR(m, s) { TCHECK(cmu->m, sizeof(cmu->m)); \
  330.     if (cmu->m.s_addr != 0) \
  331.     printf(fmt, s, ipaddr_string(&cmu->m.s_addr)); }
  332.  
  333.     /* Setup end pointer */
  334.     ep = bp + length;
  335.  
  336.     printf(" vend-cmu");
  337.     cmu = (struct cmu_vend *)bp;
  338.  
  339.     /* Only print if there are unknown bits */
  340.     TCHECK(cmu->v_flags, sizeof(cmu->v_flags));
  341.     if ((cmu->v_flags & ~(VF_SMASK)) != 0)
  342.         printf(" F:0x%x", cmu->v_flags);
  343.     PRINTCMUADDR(v_dgate, "DG");
  344.     PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*");
  345.     PRINTCMUADDR(v_dns1, "NS1");
  346.     PRINTCMUADDR(v_dns2, "NS2");
  347.     PRINTCMUADDR(v_ins1, "IEN1");
  348.     PRINTCMUADDR(v_ins2, "IEN2");
  349.     PRINTCMUADDR(v_ts1, "TS1");
  350.     PRINTCMUADDR(v_ts2, "TS2");
  351.     return;
  352.  
  353. trunc:
  354.     fputs(tstr, stdout);
  355. #undef TCHECK
  356. #undef PRINTCMUADDR
  357. }
  358.